﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using l1cs.server.model.Instance;
using l1cs.server.model.skill;
using l1cs.server.serverpackets;
using l1cs.server.datatables;
using l1cs.server.model;

namespace l1cs.server.clientpackets
{
    public class C_Chat : ClientBasePacket
    {
        private const String _C_CHAT = "[C] C_Chat";
        private static Logger _log = Logger.getLogger( typeof( C_Chat ).FullName );

        public C_Chat( byte[] abyte0, ClientThread clientthread )
            : base( abyte0 )
        {

            L1PcInstance pc = clientthread.getActiveChar();
            int chatType = readC();
            String chatText = readS();
            if ( pc.hasSkillEffect( L1SkillId.SILENCE )
                    || pc.hasSkillEffect( L1SkillId.AREA_OF_SILENCE )
                    || pc.hasSkillEffect( L1SkillId.STATUS_POISON_SILENCE ) )
            {
                return;
            }
            if ( pc.hasSkillEffect( 1005 ) )
            { // チャット禁止中
                pc.sendPackets( new S_ServerMessage( 242 ) ); // 現在チャット禁止中です。
                return;
            }

            if ( chatType == 0 )
            { // 通常チャット
                if ( pc.isGhost() && !( pc.isGm() || pc.isMonitor() ) )
                {
                    return;
                }
                // GMコマンド
                if ( chatText.StartsWith( "." ) )
                {
                    String cmd = chatText.Substring( 1 );
                    GMCommands.getInstance().handleCommands( pc, cmd );
                    return;
                }

                // トレードチャット
                // 本来はchatType==12になるはずだが、行頭の$が送信されない
                if ( chatText.StartsWith( "$" ) )
                {
                    String text = chatText.Substring( 1 );
                    chatWorld( pc, text, 12 );
                    if ( !pc.isGm() )
                    {
                        pc.checkChatInterval();
                    }
                    return;
                }

                ChatLogTable.getInstance().storeChat( pc, null, chatText, chatType );
                S_ChatPacket s_chatpacket = new S_ChatPacket( pc, chatText,
                        Opcodes.S_OPCODE_NORMALCHAT, 0 );
                if ( !pc.getExcludingList().contains( pc.getName() ) )
                {
                    pc.sendPackets( s_chatpacket );
                }
                foreach ( L1PcInstance listner in L1World.getInstance().getRecognizePlayer( pc ) )
                {
                    if ( !listner.getExcludingList().contains( pc.getName() ) )
                    {
                        listner.sendPackets( s_chatpacket );
                    }
                }
                // ドッペル処理
                foreach ( L1Object obj in pc.getKnownObjects() )
                {
                    if ( obj is L1MonsterInstance )
                    {
                        L1MonsterInstance mob = (L1MonsterInstance)obj;
                        if ( mob.getNpcTemplate().is_doppel()
                                && mob.getName().Equals( pc.getName() ) )
                        {
                            mob.broadcastPacket( new S_NpcChatPacket( mob, chatText,
                                    0 ) );
                        }
                    }
                }
            }
            else if ( chatType == 2 )
            { // 叫び
                if ( pc.isGhost() )
                {
                    return;
                }
                ChatLogTable.getInstance().storeChat( pc, null, chatText, chatType );
                S_ChatPacket s_chatpacket = new S_ChatPacket( pc, chatText,
                        Opcodes.S_OPCODE_NORMALCHAT, 2 );
                if ( !pc.getExcludingList().contains( pc.getName() ) )
                {
                    pc.sendPackets( s_chatpacket );
                }
                foreach ( L1PcInstance listner in L1World.getInstance().getVisiblePlayer(
                        pc, 50 ) )
                {
                    if ( !listner.getExcludingList().contains( pc.getName() ) )
                    {
                        listner.sendPackets( s_chatpacket );
                    }
                }

                // ドッペル処理
                foreach ( L1Object obj in pc.getKnownObjects() )
                {
                    if ( obj is L1MonsterInstance )
                    {
                        L1MonsterInstance mob = (L1MonsterInstance)obj;
                        if ( mob.getNpcTemplate().is_doppel()
                                && mob.getName().Equals( pc.getName() ) )
                        {
                            foreach ( L1PcInstance listner in L1World.getInstance()
                                    .getVisiblePlayer( mob, 50 ) )
                            {
                                listner.sendPackets( new S_NpcChatPacket( mob,
                                        chatText, 2 ) );
                            }
                        }
                    }
                }
            }
            else if ( chatType == 3 )
            { // 全体チャット
                chatWorld( pc, chatText, chatType );
            }
            else if ( chatType == 4 )
            { // 血盟チャット
                if ( pc.getClanid() != 0 )
                { // クラン所属中
                    L1Clan clan = L1World.getInstance().getClan( pc.getClanname() );
                    int rank = pc.getClanRank();
                    if ( clan != null
                            && ( rank == L1Clan.CLAN_RANK_PUBLIC
                                    || rank == L1Clan.CLAN_RANK_GUARDIAN || rank == L1Clan.CLAN_RANK_PRINCE ) )
                    {
                        ChatLogTable.getInstance().storeChat( pc, null, chatText,
                                chatType );
                        S_ChatPacket s_chatpacket = new S_ChatPacket( pc, chatText,
                                Opcodes.S_OPCODE_GLOBALCHAT, 4 );
                        L1PcInstance[] clanMembers = clan.getOnlineClanMember();
                        foreach ( L1PcInstance listner in clanMembers )
                        {
                            if ( !listner.getExcludingList().contains( pc.getName() ) )
                            {
                                listner.sendPackets( s_chatpacket );
                            }
                        }
                    }
                }
            }
            else if ( chatType == 11 )
            { // パーティーチャット
                if ( pc.isInParty() )
                { // パーティー中
                    ChatLogTable.getInstance().storeChat( pc, null, chatText, chatType );
                    S_ChatPacket s_chatpacket = new S_ChatPacket( pc, chatText, Opcodes.S_OPCODE_GLOBALCHAT, 11 );
                    L1PcInstance[] partyMembers = pc.getParty().getMembers();
                    foreach ( L1PcInstance listner in partyMembers )
                    {
                        if ( !listner.getExcludingList().contains( pc.getName() ) )
                        {
                            listner.sendPackets( s_chatpacket );
                        }
                    }
                }
            }
            else if ( chatType == 12 )
            { // トレードチャット
                chatWorld( pc, chatText, chatType );
            }
            else if ( chatType == 13 )
            { // 連合チャット
                if ( pc.getClanid() != 0 )
                { // クラン所属中
                    L1Clan clan = L1World.getInstance().getClan( pc.getClanname() );
                    int rank = pc.getClanRank();
                    if ( clan != null
                            && ( rank == L1Clan.CLAN_RANK_GUARDIAN || rank == L1Clan.CLAN_RANK_PRINCE ) )
                    {
                        ChatLogTable.getInstance().storeChat( pc, null, chatText,
                                chatType );
                        S_ChatPacket s_chatpacket = new S_ChatPacket( pc, chatText,
                                Opcodes.S_OPCODE_GLOBALCHAT, 13 );
                        L1PcInstance[] clanMembers = clan.getOnlineClanMember();
                        foreach ( L1PcInstance listner in clanMembers )
                        {
                            int listnerRank = listner.getClanRank();
                            if ( !listner.getExcludingList().contains( pc.getName() )
                                    && ( listnerRank == L1Clan.CLAN_RANK_GUARDIAN || listnerRank == L1Clan.CLAN_RANK_PRINCE ) )
                            {
                                listner.sendPackets( s_chatpacket );
                            }
                        }
                    }
                }
            }
            else if ( chatType == 14 )
            { // チャットパーティー
                if ( pc.isInChatParty() )
                { // チャットパーティー中
                    ChatLogTable.getInstance().storeChat( pc, null, chatText,
                            chatType );
                    S_ChatPacket s_chatpacket = new S_ChatPacket( pc, chatText,
                            Opcodes.S_OPCODE_NORMALCHAT, 14 );
                    L1PcInstance[] partyMembers = pc.getChatParty().getMembers();
                    foreach ( L1PcInstance listner in partyMembers )
                    {
                        if ( !listner.getExcludingList().contains( pc.getName() ) )
                        {
                            listner.sendPackets( s_chatpacket );
                        }
                    }
                }
            }
            if ( !pc.isGm() )
            {
                pc.checkChatInterval();
            }
        }

        private void chatWorld( L1PcInstance pc, String chatText, int chatType )
        {
            if ( pc.isGm() )
            {
                ChatLogTable.getInstance().storeChat( pc, null, chatText, chatType );
                L1World.getInstance().broadcastPacketToAll(
                        new S_ChatPacket( pc, chatText, Opcodes.S_OPCODE_GLOBALCHAT,
                                chatType ) );
            }
            else if ( pc.getLevel() >= Config.GLOBAL_CHAT_LEVEL )
            {
                if ( L1World.getInstance().isWorldChatElabled() )
                {
                    if ( pc.get_food() >= 6 )
                    {
                        pc.set_food( pc.get_food() - 5 );
                        ChatLogTable.getInstance().storeChat( pc, null, chatText,
                                chatType );
                        pc.sendPackets( new S_PacketBox( S_PacketBox.FOOD, pc
                                .get_food() ) );
                        foreach ( L1PcInstance listner in L1World.getInstance()
                                .getAllPlayers() )
                        {
                            if ( !listner.getExcludingList().contains( pc.getName() ) )
                            {
                                if ( listner.isShowTradeChat() && chatType == 12 )
                                {
                                    listner.sendPackets( new S_ChatPacket( pc,
                                            chatText, Opcodes.S_OPCODE_GLOBALCHAT,
                                            chatType ) );
                                }
                                else if ( listner.isShowWorldChat()
                                      && chatType == 3 )
                                {
                                    listner.sendPackets( new S_ChatPacket( pc,
                                            chatText, Opcodes.S_OPCODE_GLOBALCHAT,
                                            chatType ) );
                                }
                            }
                        }
                    }
                    else
                    {
                        pc.sendPackets( new S_ServerMessage( 462 ) ); // \f1空腹のためチャットできません。
                    }
                }
                else
                {
                    pc.sendPackets( new S_ServerMessage( 510 ) ); // 現在ワールドチャットは停止中となっております。しばらくの間ご了承くださいませ。
                }
            }
            else
            {
                pc.sendPackets( new S_ServerMessage( 195, Convert.ToString( Config.GLOBAL_CHAT_LEVEL ) ) ); // レベル%0未満のキャラクターはチャットができません。
            }
        }

        override
        public String getType()
        {
            return _C_CHAT;
        }
    }
}